package v3

import (
	"bytes"
	"crypto/sha256"
	"fmt"
	"math/big"
)

// 工作量证明
type ProofOfWork struct {
	block *Block
	//目标难度值
	target *big.Int
}

// 创建工作量证明对象
func NewProofOfWork(b *Block) *ProofOfWork {
	str := "00000f0000000000000000000000000000000000000000000000000000000000"
	tempInt := big.Int{}
	//16代表进制
	tempInt.SetString(str, 16)
	return &ProofOfWork{block: b, target: &tempInt}
}

// 工作量证明->hash和随机数Nonce
func (proofOfWork *ProofOfWork) run() (hash []byte, Nonce uint64) {
	block := proofOfWork.block
	var nonce uint64
	tempInt := big.Int{}
	for {
		s := [][]byte{
			Uint64ToBytes(block.Version),
			block.PreHash,
			block.MerkleRoot,
			Uint64ToBytes(block.Timestamp),
			Uint64ToBytes(block.Difficulty),
			Uint64ToBytes(nonce),
			block.Data,
		}
		data := bytes.Join(s, []byte{})
		sha256Bytes := sha256.Sum256(data)
		tempInt.SetBytes(sha256Bytes[:])
		//   - -1 if x < y;
		//   - 0 if x == y;
		//   - +1 if x > y.
		//hash值比目标值小就返回找到了,挖矿成功
		if tempInt.Cmp(proofOfWork.target) == -1 {
			fmt.Printf("挖矿成功,找到了比目标值小的hash: %x ,随机值: %d \n", sha256Bytes, nonce)
			return sha256Bytes[:], nonce
		} else {
			nonce++
		}
	}
}
